
#include <stdio.h>
#include <windows.h>
#include <Winsock2.h>
#include <iostream>

using namespace std;

#define REQUEST_BACKLOG 5
//****************************** 
//好吧不用写这些纠结的函数，就是看着清晰些 
//初始化Winsock 

bool InitWSA( const WORD &wVersion, WSADATA *wsadata ) 
{ 
    int Ret; 
	Ret = WSAStartup(wVersion, wsadata);
    if ( Ret != 0 ) 
    {
		printf("WSAStartup failed, error %d\n", Ret);
        return false; 
    } 
    return true; 
} 

//结束Winsock 
void cleanWSA() 
{ 
    if ( WSACleanup() == SOCKET_ERROR ) 
    {
		printf("WSACleanup failed, error %d\n", WSAGetLastError());
    } 
} 

//IPv4寻址，通过ip填充SOCKADDR_IN结构 
void InitSockAddrByIP( SOCKADDR_IN *pSockAddr, const char *strIP, const INT &nPortID ) 
{ 
    pSockAddr->sin_family = AF_INET; 
    pSockAddr->sin_port   = htons(nPortID); 
    if ( 0 != strlen(strIP) ) 
        pSockAddr->sin_addr.s_addr = inet_addr( strIP ); 
    else 
        pSockAddr->sin_addr.s_addr = htonl( INADDR_ANY ); 
} 

//bind 
bool bindAddr( const SOCKADDR_IN *pSockAddr, SOCKET *pSocket ) 
{ 
    int bindResult = bind( *pSocket, (sockaddr *)(pSockAddr), sizeof(*pSockAddr)); 
    if ( SOCKET_ERROR == bindResult ) 
    {
		printf("bind error : %d\n", WSAGetLastError());
        return false; 
    }  
    return true; 
} 

//listen 
bool setListener( SOCKET *pSocket, int backlog ) 
{ 
    int nResult = listen( *pSocket, backlog ); 
    if ( SOCKET_ERROR == nResult ) 
    { 
		printf("listen error : %d\n", WSAGetLastError());
        return false; 
    }  
    return true; 
}

//****************************** 
//程序入口 
int main(int argc, char* argv[]) 
{ 
    //初始化Winsock 
    WSADATA wsadata; 
    if ( !InitWSA( MAKEWORD(2,2), &wsadata ) )  { 
        return 0; 
    } 
    //指定连接ip地址和服务器口 
    SOCKADDR_IN InternetAddr; 
    //char strIP[]  = "198.0.0.0"; 
    char strIP[]    = ""; 
    int nPortID         = 21; 
    InitSockAddrByIP( &InternetAddr, strIP, nPortID ); 
	
    //创建listener_socket 
    SOCKET listener_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); 
    if ( INVALID_SOCKET == listener_socket ) 
    { 
		printf("listener_socket creat failed \n");
        return 0; 
    } 
    //bind 
    if ( !bindAddr( &InternetAddr, &listener_socket ) ) 
    { 
        return 0; 
    } 
    //监听 
    if ( !setListener( &listener_socket, REQUEST_BACKLOG ) ) 
    {
        return 0; 
    }
	printf("server started~~~ \n");

    //创建socket保存结构 
    ////fd_set fdSocket; 
    ////FD_ZERO( &fdSocket ); 
    ////FD_SET( listener_socket, &fdSocket );
	
	struct sockaddr_in client;
	int iSize;
	SOCKET client_socket;
	char sendbuff[2048]; 
    char recvbuff[2048]; 
	int ret;

	iSize = sizeof(client);
	client_socket = accept(listener_socket, (sockaddr*)&client, &iSize);
	if ( INVALID_SOCKET == client_socket ) 
	{
		printf(" accept error %d\n", WSAGetLastError());
		exit(0);
	} 
	printf("find new connect: %s\n", inet_ntoa(client.sin_addr)); 
step_1:
	ret = recv(client_socket, recvbuff, sizeof(recvbuff), 0);
	if (ret == 0)
	{
	}
	else if (ret == SOCKET_ERROR)
	{
		printf("recv fail %s! \n", WSAGetLastError());
	}
	recvbuff[ret] = 0;
	if (strcmp(recvbuff, "hello\r\n"))
		goto step_1;
	printf("RECV: %s", recvbuff);
		
	strcpy(sendbuff, "good\r\n");
	ret = send(client_socket, sendbuff, strlen(sendbuff), 0);
		
	printf("send good finish\n");
		
step_2:
	ret = recv(client_socket, recvbuff, sizeof(recvbuff), 0);
	recvbuff[ret] = 0;
	if (strncmp(recvbuff, "length:", 7)) {
		printf("length error\n");
		goto step_2;
	}
	printf("get length finish\n");
	
	int length = 0;
	for (int i = 7; i < strlen(recvbuff); i++)
	{
		if (recvbuff[i] >= '0' && recvbuff[i] <= '9')
		{
			length *= 10;
			length += (recvbuff[i] - '0');
		}
		else
			break;
	}
	printf("length = %d\n", length);

	sprintf(sendbuff, "ok:%d\r\n", length);
	ret = send(client_socket, sendbuff, strlen(sendbuff), 0);
	
	/////
	printf("create file\n");
	FILE * fp;
	fp = fopen("C:\\1.jpg", "wb");
	int total;
	total = length;
	while (1)
	{
		ret = recv(client_socket, recvbuff, sizeof(recvbuff), 0);
		if (ret < 0) {
		printf("error \n");
			break;
		}
		if (ret == 0) {
			printf("finish");
			break;
			}
		fwrite(recvbuff, 1, ret, fp);
		printf("write %d byte\n", ret);
		total -= ret;
		if (total <= 0)
			break;
	}
	
	fclose(fp);
	
		
	closesocket(client_socket);
		


	
	
	#if 0
    //查找可读的socket 
    while( true ) 
    { 
        fd_set fdSocket_temp; 
        fdSocket_temp = fdSocket; 
        fd_set fdRead; 
        fdRead = fdSocket; 
        fd_set fdExceptds; 
        fdExceptds = fdSocket; 
        int nResult_select = select( 0, &fdRead, NULL, &fdExceptds, NULL ); 
        if ( 0 < nResult_select ) 
        { 
            unsigned int socket_count = fdSocket_temp.fd_count; 
            for ( unsigned int i=0; i< socket_count; i++ ) 
            { 
                //可读的 
                if ( FD_ISSET( fdSocket_temp.fd_array[i], &fdRead ) ) 
                { 
                    //找到所有可读连接 
                    if ( fdSocket_temp.fd_array[i] == listener_socket ) 
                    { 
                        if ( fdSocket.fd_count < FD_SETSIZE ) 
                        { 
                            //接受新的连接 
                            SOCKADDR_IN ClientAddr; 
                            int addrlen = static_cast<int>(sizeof(ClientAddr));   //一定要赋值 
                            SOCKET newClient_socket = accept( listener_socket, (sockaddr *)&ClientAddr, &addrlen ); 
                            if ( INVALID_SOCKET == newClient_socket ) 
                            { 
								printf(" accept error %d\n", WSAGetLastError());
                            } 
                            else 
                            { 
                                FD_SET( newClient_socket, &fdSocket ); 
                                cout << "find new connect: " << inet_ntoa( ClientAddr.sin_addr ) << endl; 
                            } 
                        } 
                        else 
                        {
							printf("too much connections\n");
                            continue; 
                        } 
                    }  
                    else 
                    { 
                        //接收数据 
                        char recvbuff[1024]; 
                        int  ret = 0; 
                        ret = recv( fdSocket_temp.fd_array[i], recvbuff, static_cast<int>( strlen(recvbuff) ), 0 ); 
                        if ( 0 < ret ) 
                        { 
                            recvbuff[ret] = '\0'; 
                            cout << "recv : " << recvbuff << endl; 
                            //回复 
                            char backbuf[1024] = "receive info!"; 
                            send( fdSocket_temp.fd_array[i], backbuf, static_cast<int>( strlen(backbuf) ), 0 ); 
                        } 
                        else 
                        { 
                            //该连接断开 
                            closesocket( fdSocket_temp.fd_array[i] ); 
                            FD_CLR( fdSocket_temp.fd_array[i], &fdSocket ); 
                        }
                    } 
                } 
                else if( fdSocket_temp.fd_array[i] != listener_socket ) 
                { 
                    //该连接断开 
                    closesocket( fdSocket_temp.fd_array[i] ); 
                    FD_CLR( fdSocket_temp.fd_array[i], &fdSocket ); 
                } 

                if ( FD_ISSET( fdSocket_temp.fd_array[i], &fdExceptds )  &&  (fdSocket_temp.fd_array[i] != listener_socket) ) 
                { 
                    //该连接断开 
                    closesocket( fdSocket_temp.fd_array[i] ); 
                    FD_CLR( fdSocket_temp.fd_array[i], &fdSocket ); 
                } 
            }//end for 
        } 
        else if( SOCKET_ERROR == nResult_select ) 
        { 
            cout << "select error : " << WSAGetLastError() << endl; 
            return 0; 
        } 
        Sleep( 50 );    //不要挑战你的机器 
    }//end while 
	#endif
	
	
    closesocket( listener_socket ); 
    cleanWSA(); 
    return 0; 

} 




